/*
 * @Author: xiaosihan 
 * @Date: 2022-01-07 16:26:41 
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2022-06-14 18:58:20
 */

import { Color, CubicBezierCurve3, Mesh, ShaderChunk, ShaderMaterial, TubeGeometry, Vector3 } from "three";


type FlyLineOption = {
    start?: { x: number, y: number, z: number },
    end?: { x: number, y: number, z: number },
    radius?: number,
}

/**
 * 飞线模型
 */
export default class FlyLine extends Mesh {

    constructor(option: FlyLineOption = {}) {
        super();

        this.init();

        const { start = { x: 0, y: 0, z: 0 }, end = { x: 0, y: 0, z: 0 }, radius = 300 } = option;

        this._start.set(start.x, start.y, start.z);
        this._end.set(end.x, end.y, end.z);
        this._radius = radius;
        this.updateGeometry();
    }

    init() {
    }

    isFlyLine = true;

    renderOrder = 20;

    // 线的颜色
    _lineColor = "#ffd669";

    set lineColor(c: string) {
        this._lineColor = c;
        this.material.uniforms.lineColor.value.set(c);
    }
    get lineColor() {
        return this._lineColor;
    }

    _start = new Vector3(0, 0, 0);
    _end = new Vector3(0, 0, 0);
    _radius = 0.1;

    // 更新网格
    updateGeometry() {

        const direction = new Vector3(); // 飞线的方向

        const length = this._start.distanceTo(this._end); // 飞线的水平长度

        const path: Vector3[] = [];

        for (let i = 0; i < 4; i++) {
            direction.copy(this._end).sub(this._start).normalize().multiplyScalar(length / 3 * i);
            if ([1, 2].includes(i)) {
                direction.y += (1.5 - Math.abs(i - 1.5)) * length / 2;
            }
            path.push(this._start.clone().add(direction));
        }

        var curve = new CubicBezierCurve3(path[0], path[1], path[2], path[3]);

        this.geometry.dispose();

        this.geometry = new TubeGeometry(curve, 50, this._radius, 3, false);
    }

    material = new ShaderMaterial({
        uniforms: {
            lineColor: {
                value: new Color(this._lineColor) // 线的颜色
            },
            showProgress: { // 显示进度
                value: 1
            }
        },
        vertexShader: `
            ${ShaderChunk.common}
            ${ShaderChunk.logdepthbuf_pars_vertex}
            varying vec2 vUv;
            void main() {
                vUv = uv;
                gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
                ${ShaderChunk.logdepthbuf_vertex}
            }
        `,
        fragmentShader: `
            ${ShaderChunk.logdepthbuf_pars_fragment}
            uniform vec3 lineColor; // 线的颜色
            uniform float showProgress; // 显示进度
            varying vec2 vUv;


            float opacity(){

                if(showProgress * 1.6 < vUv.x){
                    return 0.0;
                }

                return 1.0 - ((showProgress * 1.8 - vUv.x) * 1.666 );
            }


            void main() {
                gl_FragColor = vec4(lineColor, opacity() );
                // gl_FragColor = vec4(lineColor,  (abs(showProgress - vUv.x) < 0.01 ? 1.0 : 0.0) * (0.5 - abs(vUv.x - 0.5)  ) * 0.5  );
                ${ShaderChunk.logdepthbuf_fragment}
            }
        `,
        // blending: THREE.NoBlending,
        // side: FrontSide,
        depthTest: true,
        depthWrite: true,
        transparent: true
    });

}